package sit.mycatalog.util;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.TypedQuery;

import sit.mycatalog.jpa.AbstractEntity;

public abstract class AbstractDao<T> {
	@PersistenceContext(unitName = "mycatalog-jpa")
	protected EntityManager em;

	private Class<T> m_entityClass;

	public AbstractDao(Class<T> entityClass) {
		m_entityClass = entityClass;
	}

	public boolean create(T entity) throws Exception {
		boolean isComplete = false;

		try {
			em.persist(entity);
			isComplete = true;
		} catch (Exception e) {
			throw new Exception("create(): " + e.getMessage(), e);
		}

		return isComplete;
	}

	public boolean remove(Object entityId) throws Exception {
		boolean isComplete = false;

		try {
			em.remove(findByPrimaryKey(entityId));
			isComplete = true;
		} catch (Exception e) {
			throw new Exception("remove(): " + e.getMessage(), e);
		}

		return isComplete;
	}

	public T findByPrimaryKey(Object entityId) throws Exception {
		T t = em.find(m_entityClass, entityId);

		if (t == null) {
			t = m_entityClass.newInstance();
			((AbstractEntity) t).setCheck(false);
		} else {
			((AbstractEntity) t).setCheck(true);
		}

		return t;
	}

	public T findByPrimaryKeyDetach(Object entityId) throws Exception {
		T t = findByPrimaryKey(entityId);
		em.detach(t);

		return t;
	}
	
	public List<T> findList(String sql) throws Exception {
		TypedQuery<T> tq = createTypedQuery(sql);
		
		return tq.getResultList();
	}
	
	public List<T> findList(StringBuffer sql) throws Exception {
		return findList(sql.toString());
	}
	
	public List<T> findList(StringBuilder sql) throws Exception {
		return findList(sql.toString());
	}
	
	public List<T> findList(String sql, ParamBinder pb) throws Exception {
		TypedQuery<T> tq = createTypedQuery(sql);
		pb.bind(tq);
		
		return tq.getResultList();
	}
	
	public List<T> findList(StringBuffer sql, ParamBinder pb) throws Exception {
		return findList(sql.toString(), pb);
	}
	
	public List<T> findList(StringBuilder sql, ParamBinder pb) throws Exception {
		return findList(sql.toString(), pb);
	}
	
	public Object findObject(String sql) throws Exception {
		Query q = createQuery(sql);
		
		return q.getSingleResult();
	}
	
	public Object findObject(StringBuffer sql) throws Exception {
		return findObject(sql.toString());
	}
	
	public Object findObject(StringBuilder sql) throws Exception {
		return findObject(sql.toString());
	}
	
	public Object findObject(String sql, ParamBinder pb) throws Exception {
		Query q = createQuery(sql);
		pb.bind(q);
		
		return q.getSingleResult();
	}
	
	public Object findObject(StringBuffer sql, ParamBinder pb) throws Exception {
		return findObject(sql.toString(), pb);
	}
	
	public Object findObject(StringBuilder sql, ParamBinder pb) throws Exception {
		return findObject(sql.toString(), pb);
	}

//	public void edit(T entity) throws Exception {
//		em.merge(entity);
//	}
	
	public TypedQuery<T> createTypedQuery(String sql) {
		TypedQuery<T> tq = em.createQuery(sql.toString(), m_entityClass);

		return tq;
	}

	public TypedQuery<T> createTypedQuery(StringBuffer sql) {
		return createTypedQuery(sql.toString());
	}

	public TypedQuery<T> createTypedQuery(StringBuilder sql) {
		return createTypedQuery(sql.toString());
	}

	public Query createQuery(String sql) {
		Query q = em.createQuery(sql.toString());

		return q;
	}

	public Query createQuery(StringBuffer sql) {
		return createQuery(sql.toString());
	}

	public Query createQuery(StringBuilder sql) {
		return createQuery(sql.toString());
	}
}